package com.edu.learning.concurrent.sample.mode1;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.*;

/**
 * 线程安全队列Queue实现线程同步问题：生产者-消费者模型
 *
 * @author ll
 * @Date 2017/10/24 20:50
 */
public class ConcurrentLinkedQueueDemo {
    public static void main(String[] args) {
        // 线程操作安全队列，装载数据
        Queue<String> queue = new ConcurrentLinkedQueue<String>();

        ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("ConcurrentLinkedQueueDemo-%d").build();
        ExecutorService singleThreadPool = new ThreadPoolExecutor(
                32,
                32,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(2),
                namedThreadFactory,
                new ThreadPoolExecutor.CallerRunsPolicy());

//        singleThreadPool.execute(()-> System.out.println(Thread.currentThread().getName()));
//        singleThreadPool.shutdown();

        // 消费者线程：不断的消费队列中的数据
        // 该线程不停的从队列中取出队列中最头部的数据
        //new Thread(new Runnable() {
        singleThreadPool.execute(new Runnable() {

            @Override
            public void run() {
                while (true) {
                    // 从队列的头部取出并删除该条数据
                    String s = queue.poll();
                    if (s != null) {
                        System.out.println(Instant.now() + "\t 取出数据： " + s);
                    }
                }
            }
        });

        // 生产者线程A：不断的生产单个数据并装入队列中
        // 该线程模拟不停的在队列中装入一个数据
        //new Thread(new Runnable() {
        singleThreadPool.execute(new Runnable() {
            private int count = 0;
            private int number = 0;

            @Override
            public void run() {
                while (true) {
                    number = count++;
                    System.out.println("装载数据：" + number);
                    queue.add(String.valueOf(number));

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        // 生产者线程B：不断的生产批量数据并装入队列中
        // 该线程模拟不停的在队列中装入一批数据
        //new Thread(new Runnable() {
        singleThreadPool.execute(new Runnable() {
            private List<String> list = new ArrayList<String>();
            private int count = 0;

            @Override
            public void run() {
                while (true) {
                    // 一批数据的数量，不定长
                    count = (int) (Math.random() * 5);
                    for (int i = 0; i < count; i++) {
                        list.add("\t 批量装载数据-" + i + "," + Math.random());
                    }

                    queue.addAll(list);
                    list.clear();

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }
}
